package torres.item;

import java.util.ArrayList;

import torres.fileIO.BasicContainer;
import torres.fileIO.ClassContainer;
import torres.fileIO.PropertyContainer;
import torres.fileIO.Saveable;


/**
 * @author Torres
 * Represents an Entity's equipped items. 
 * Allows items to be added and removed.
 * Calculates the armor mod and offensive mod of all
 * equipped items.
 */
public class EquippedInventory implements Saveable
{
	/*
	 * private EquippableItem headItem;
	private EquippableItem leftHandItem;
	private EquippableItem rightHandItem;
	private EquippableItem lowerBodyItem;
	private EquippableItem upperBodyItem;
	*/
	
	private EquippableItem equipArray[];
	private ArrayList<EquippableItem> equipList;
	
	/**
	 * Default constructor for the EquippedInventory
	 */
	public EquippedInventory() {
		
		//headItem = leftHandItem = rightHandItem = lowerBodyItem = upperBodyItem = null;
		equipArray = new EquippableItem[6]; 
		equipList = new ArrayList<EquippableItem>();
	}
	
	/** 
	 * Add the specified item to the EquippedInventory
	 * @param The item to be added to the EquippedInventory
	 * @return True if the item was equipped, false otherwise.
	 */
	public synchronized boolean addItem(EquippableItem item)	{
		boolean returnValue = true;
		int index = item.equipType.ordinal();
		if(equipArray[index] == null) {
			equipArray[index] = item;
			equipList.add(item);
		}
		else {
			returnValue = false;
		}
		return returnValue;
	}
	
	
	/**
	 * Adds given weapon to EquippedInventory if not full or other weapon occupies slot
	 * @param w Weapon to be added
	 * @return true if added, else false
	 */
	public synchronized boolean addWeapon(Weapon w) {
		boolean returnValue = true;
		switch(w.getWeaponType()) {
			case TWO_HANDED:
			case STAFF:
				if(equipArray[EquipType.LEFT.ordinal()] == null && equipArray[EquipType.RIGHT.ordinal()] == null) {
					equipArray[EquipType.LEFT.ordinal()] = w;
					equipArray[EquipType.RIGHT.ordinal()] = w;
					equipList.add(w);
				}
				else
					returnValue = false;
				break;
			case ONE_HANDED:
			case BRAWLING:
			case RANGED:
				if(equipArray[w.getType().ordinal()] == null) {
					equipArray[w.getType().ordinal()] = w;
					equipList.add(w);
				}
				else
					returnValue = false;
		}
		return returnValue;
	}
	
	
	/**
	 * Remove the specified item from the inventory, if it exists.
	 * @param item The item to be removed from the inventory.
	 * @return The item removed, if successful. Null otherwise.
	 */
	public EquippableItem removeItem(EquippableItem item) {
		EquippableItem returnValue = null;
		int index = item.equipType.ordinal();
		returnValue = equipArray[index];
		equipArray[index] = null;
		equipList.remove(item);
		return returnValue;
	}
	
	public EquippableItem removeWeapon(Weapon w) {
		EquippableItem returnValue = null;
		
		switch(w.getWeaponType()) {
			case TWO_HANDED:
			case STAFF:
				returnValue = equipArray[EquipType.LEFT.ordinal()];
				equipArray[EquipType.LEFT.ordinal()] = null;
				equipArray[EquipType.RIGHT.ordinal()] = null;
				equipList.remove(w);
				break;
			case ONE_HANDED:
			case BRAWLING:
			case RANGED:
				returnValue = equipArray[w.getType().ordinal()];
				equipArray[w.getType().ordinal()] = null;
				equipList.remove(w);
		}
		return returnValue;
	}

	/**
	 * Returns the total Armor Modifier of all equipped items.
	 * @return The total Armor Modifier of all equipped items, 0 if nothing is equipped.
	 */
	public int getArmorTotal() {
		int total = 0;
		for(int i = 0; i < equipArray.length; ++i) 
			if(equipArray[i] != null)
				total += equipArray[i].getArmorMod();
		return total;
	}

	/**
	 * Returns the total Weapon Modifier of all equipped items.
	 * @return The total Weapon Modifier of all equipped items, 0 if nothing is equipped.
	 */
	public int getWeaponTotal() {
		int total = 0;
		for(int i = 0; i < equipArray.length; ++i) 
			if(equipArray[i] != null)
				total += equipArray[i].getOffensiveMod();
		return total;
	}
	
	
	/**
	 * Retrieves the item at the specified index.
	 * @param index The index of the item to be fetched.
	 * @return The item at the specified index if it exists, null otherwise.
	 */
	public EquippableItem getItem(int index) {
		return equipArray[index];
	}
	
	
	/**
	 * Returns the array representing the player's equipped inventory.
	 * @return The array representing the player's equipped inventory.
	 */
	public EquippableItem[] getItemArray() {
		return equipArray;
	}
	
	/**
	 * Returns the player's list of equipped items.
	 * @return ArrayList of player's equipped items
	 */
	public ArrayList<EquippableItem> getItemList() {
		return equipList;
	}
	/**
	 * Tests if the specified item is equipped.
	 * @param item The item to be tested.
	 * @return True if the item is equipped, false otherwise.
	 */
	public boolean hasItem(TakeableItem item) {

		boolean returnValue = false;
		for(int a = 0; a < equipArray.length; ++a) 
			returnValue = returnValue || equipArray[a].equals(item);
		return returnValue;
	}

	
	/**
	 * Retrieves the item that is currently equipped to the head.
	 * @return The item that is equipped on the Head.
	 */
	public EquippableItem getHeadItem() {
		
		return this.equipArray[EquipType.HEAD.ordinal()]; 
	}
	
	/**
	 * Retrieves the item that is currently equipped to the left hand.
	 * @return The item that is equipped on the left hand.
	 */
	public EquippableItem getLeftHandItem() {
		
		return this.equipArray[EquipType.LEFT.ordinal()];
	}
	
	/**
	 * Retrieves the item that is currently equipped to the right hand.
	 * @return The item that is equipped on the right hand.
	 */
	public EquippableItem getRightHandItem() {
		
		return this.equipArray[EquipType.RIGHT.ordinal()];
	}
	
	/**
	 * Retrieves the item that is currently equipped to the Upper body.
	 * @return The item that is equipped on the Upper body.
	 */
	public EquippableItem getUpperBodyItem() {
		
		return this.equipArray[EquipType.UPPER.ordinal()];
	}
	
	/**
	 * Retrieves the item that is currently equipped to the Lower body.
	 * @return The item that is equipped on the Lower body.
	 */
	public EquippableItem getLowerBodyItem() {
		
		return this.equipArray[EquipType.LOWER.ordinal()];
	}

	/**
	 * Retrives the item that is currently equipped to the accessory slot.
	 * @return Item that is equipped in accessory slot
	 */
	public EquippableItem getAccessoryItem() {
		return this.equipArray[EquipType.ACCESSORY.ordinal()];
	}
	
	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#save()
	 */
	@Override
	public ClassContainer save() {
		ClassContainer curClass = new ClassContainer("EquippedInventory");
		for(int i=0; i<equipArray.length; i++)
			if(equipArray[i]!=null)curClass.addProperty(new BasicContainer("Slot "+i, equipArray[i]));
			else curClass.addProperty(new BasicContainer("Slot "+i, -1));
		return curClass;
	}

	/* (non-Javadoc)
	 * @see torres.fileIO.Saveable#load(torres.fileIO.ClassContainer)
	 */
	@Override
	public void load(ClassContainer classContainer) {
//		ClassContainer item = (ClassContainer)classContainer.getProperty("Tiles");
		BasicContainer idCont;
		PropertyContainer property;
		int i=0;
		int id;
		while((property = classContainer.getProperty("Item", i))!=null) {
			idCont = (BasicContainer)((ClassContainer)property).getProperty("Slot "+i);
			id = (Integer)idCont.getValue();
			if(id !=-1)
				equipArray[i] = ItemManager.getInstance().getEquippableItem(id);
			i++;
		}
	}
}
